class Vue {
  constructor( options ) {
    const { beforeCreate, created, beforeMount, mounted } = options;
    this.$options = options;
    this.$watchEvent = {};
    if(typeof beforeCreate == 'function')
      beforeCreate.bind(this)();
    this.$data = options.data;
    this.proxyData();
    this.observe();
    if(typeof created == 'function')
      created.bind(this)();
    if(typeof created == 'function')
      beforeMount.bind(this)();
    this.$el = document.querySelector(options.el);
    if(typeof created == 'function')
      mounted.bind(this)();
    // 模板解析
    this.compile(this.$el);
  }

  // 1. 将$data的值赋值到外部中
  // 2. 保证双向绑定

  // 这里只是做了一个代理而已
  proxyData() {
    for(let key in this.$data) {
      // 在this上面挂载对象的值
      Object.defineProperty(this, key, {
        get() {
          return this.$data[key];
        },
        set(val) {
          // 这里的数据发生修改会引起，observe里面的set进行调用
          this.$data[key] = val;
        }
      });
    }
  }
  // 触发data中的数据发生变化来执行watch中的update变化
  observe() {
    for(let key in this.$data) {
      let value = this.$data[key];
      let that = this;
      Object.defineProperty(this.$data, key, {
        get() {
          return value;
        },
        set(val) {
          value = val;
          // 监听到数据发生变化后，需要将对应的dom数据进行改变
          if(that.$watchEvent[key]) {
            that.$watchEvent[key].forEach((item, index) => {
              item.update();
            });
          }
        }
      })
    }
  }
  compile(node) {
    // 遍历节点
    // console.log(node.childNodes);
    node.childNodes.forEach((item, index) => {
      // console.log(item);
      // console.log(item.nodeType);
      // 元素节点
      if(item.nodeType == 1) {
        // click属性
        if(item.hasAttribute('@click')) {
          // @click绑定的名称
          const funName = item.getAttribute('@click').trim();
          const { methods } = this.$options;
          // 添加事件
          item.addEventListener('click', (event) => {
            this.eventFn = methods[funName].bind(this);
            this.eventFn(event);
          });
          
        }
        if(item.childNodes.length > 0) {
          this.compile(item);
        }
      }
      // 节点类型为3，为文本节点
      if(item.nodeType == 3) {
        // 正则匹配
        let reg = /\{\{(.*?)\}\}/g;
        let text = item.textContent;
        // 给节点赋值
        item.textContent = text.replace(reg, (match, vmKey) => {
          vmKey = vmKey.trim();
          // 数据的双向绑定
          if(this.hasOwnProperty(vmKey)) {

            let watcher = new Watch(this, vmKey, item, 'textContent');

            if(this.$watchEvent[vmKey]) {
              this.$watchEvent[vmKey].push(watcher);
            } else {
              this.$watchEvent[vmKey] = [];
              this.$watchEvent[vmKey].push(watcher);
            }
          }
          return this.$data[vmKey];
        });
      }
    })
  }
}


class Watch {
  constructor(vm, key, node, attr) {
    this.vm = vm;
    this.key = key;
    this.node = node;
    this.attr = attr;
  }
  // 执行改变update操作
  update() {
    this.node[this.attr] = this.vm[this.key];
  }
}

